import random
from datetime import datetime, timedelta

# 地区代码示例，这里只用北京的一个区作为例子
area_codes = ['110101']  # 北京市东城区

# 权重因子
weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]

# 校验码表
check_codes = '10X98765432'

def generate_unique_id_number(existing_ids, base_year):
    """生成唯一的身份证号码"""
    while True:
        id_number = _generate_id_number(base_year)
        if id_number not in existing_ids:
            return id_number

def _generate_id_number(base_year):
    """生成一个随机的身份证号码"""
    current_date = datetime.now()
    one_year_ago = current_date - timedelta(days=365)

    birth_year = str(base_year)
    birth_month = f"{random.randint(1, 12):02d}"
    birth_day = f"{random.randint(1, 28):02d}"  # 简化处理，不考虑每个月的具体天数
    birth_date_str = f"{birth_year}{birth_month}{birth_day}"

    birth_date = datetime.strptime(birth_date_str, '%Y%m%d')
    if (current_date - birth_date).days < 365:
        raise ValueError("生成的身份证号码对应的出生日期必须至少为一年以前")

    sequence_code = f"{random.randint(1, 999):03d}"
    id_without_check = random.choice(area_codes) + birth_date_str + sequence_code
    check_sum = sum([int(id_without_check[i]) * weights[i] for i in range(17)])
    check_code = check_codes[check_sum % 11]
    id_number = id_without_check + check_code

    if len(id_number) != 18 or not (
            id_number[:-1].isdigit() and (id_number[-1].isdigit() or id_number[-1].upper() == 'X')):
        raise ValueError(f"生成的身份证号码 {id_number} 不符合18位的要求")

    return id_number

def extract_birth_date(id_number):
    """从身份证号码中提取出生日期"""
    if len(id_number) != 18 or not (
            id_number[:-1].isdigit() and (id_number[-1].isdigit() or id_number[-1].upper() == 'X')):
        raise ValueError(f"身份证号码 {id_number} 必须是18位数字或包含最后一位为X")

    birth_date_str = id_number[6:14]
    try:
        birth_date = datetime.strptime(birth_date_str, '%Y%m%d')
        return birth_date.strftime('%Y-%m-%d')
    except ValueError:
        raise ValueError(f"身份证号码中的出生日期部分 {birth_date_str} 不是有效日期")

def calculate_age(birth_date_str):
    """根据身份证号码中的出生日期计算年龄"""
    birth_date = datetime.strptime(birth_date_str, '%Y%m%d')
    today = datetime.today()
    age = today.year - birth_date.year - ((today.month, today.day) < (birth_date.month, birth_date.day))
    return age

# 示例调用
if __name__ == "__main__":
    existing_ids = set()
    base_year = 1980

    for i in range(10):  # 生成5个身份证号码
        try:
            id_number = generate_unique_id_number(existing_ids, base_year)
            existing_ids.add(id_number)
            print(f"生成的身份证号码: {id_number}")
            birth_date = extract_birth_date(id_number)
            print(f"出生日期: {birth_date}")
            age = calculate_age(birth_date.replace('-', ''))
            print(f"年龄: {age}")
            base_year += 2  # 每次增加2年
        except ValueError as e:
            print(f"生成第 {i+1} 个身份证号码时出错: {e}")